package cuongnh.project.japanesediary.vocabulary.model;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "tbl_category")
public class Category extends AbstractModelObject {

	@Id
	@Column(name = "category_id")
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "category_seq")
	@SequenceGenerator(name = "category_seq", sequenceName = "category_sequence", allocationSize = 1)
	private Long categoryId;

	@Column(name = "category_name", length = 100)
	private String categoryName;

	@Column(name = "description", length = 200)
	private String description;

	@ManyToOne
	@JoinColumn(name = "parent_category_id")
	private Category parentCategory;
	
	@Column(name = "created_date")
	private Date createdDate;

	@Column(name = "modified_date")
	private Date modifiedDate;

	@OneToMany(cascade = {CascadeType.ALL}, mappedBy = "parentCategory", fetch = FetchType.LAZY)
	private Set<Category> subCategories = new HashSet<Category>();

	@ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_vocabulary_category", joinColumns = { @JoinColumn(name = "category_id") }, inverseJoinColumns = { @JoinColumn(name = "vocabulary_id") })
	private Set<Vocabulary> vocabularies = new HashSet<Vocabulary>();

	@ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_grammar_category", joinColumns = { @JoinColumn(name = "category_id") }, inverseJoinColumns = { @JoinColumn(name = "grammar_id") })
	private Set<Grammar> grammars = new HashSet<Grammar>();

	@ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_kanji_category", joinColumns = { @JoinColumn(name = "category_id") }, inverseJoinColumns = { @JoinColumn(name = "kanji_id") })
	private Set<Kanji> kanjis = new HashSet<Kanji>();

	@ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_sentence_category", joinColumns = { @JoinColumn(name = "category_id") }, inverseJoinColumns = { @JoinColumn(name = "sentence_id") })
	private Set<Sentence> sentences = new HashSet<Sentence>();

	public long getCategoryId() {
		return categoryId;
	}

	public void setCategoryId(long categoryId) {
		long oldValue = this.categoryId;
		this.categoryId = categoryId;
		firePropertyChange("categoryId", oldValue, categoryId);
	}

	public String getCategoryName() {
		return categoryName;
	}

	public void setCategoryName(String categoryName) {
		String oldValue = this.categoryName;
		this.categoryName = categoryName;
		firePropertyChange("categoryName", oldValue, categoryName);
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		String oldValue = this.description;
		this.description = description;
		firePropertyChange("description", oldValue, description);
	}

	public Category getParentCategory() {
		return parentCategory;
	}

	public void setParentCategory(Category parentCategory) {
		Category oldValue = this.parentCategory;
		this.parentCategory = parentCategory;
		firePropertyChange("parentCategory", oldValue, parentCategory);
	}

	public Set<Category> getSubCategories() {
		return subCategories;
	}

	public void setSubCategories(Set<Category> subCategories) {
		Set<Category> oldValue = this.subCategories;
		this.subCategories = subCategories;
		firePropertyChange("subCategories", oldValue, subCategories);
	}

	public Set<Vocabulary> getVocabularies() {
		return vocabularies;

	}

	public void setVocabularies(Set<Vocabulary> vocabularies) {
		Set<Vocabulary> oldValue = this.vocabularies;
		this.vocabularies = vocabularies;
		firePropertyChange("vocabularies", oldValue, vocabularies);
	}

	public Set<Grammar> getGrammars() {
		return grammars;
	}

	public void setGrammars(Set<Grammar> grammars) {
		Set<Grammar> oldValue = this.grammars;
		this.grammars = grammars;
		firePropertyChange("grammars", oldValue, grammars);
	}

	public Set<Kanji> getKanjis() {
		return kanjis;
	}

	public void setKanjis(Set<Kanji> kanjis) {
		Set<Kanji> oldValue = this.kanjis;
		this.kanjis = kanjis;
		firePropertyChange("kanjis", oldValue, kanjis);
	}

	public Set<Sentence> getSentences() {
		return sentences;
	}

	public void setSentences(Set<Sentence> sentences) {
		Set<Sentence> oldValue = this.sentences;
		this.sentences = sentences;
		firePropertyChange("sentences", oldValue, sentences);
	}

	public Date getCreatedDate() {
		return createdDate;
	}

	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}

	public Date getModifiedDate() {
		return modifiedDate;
	}

	public void setModifiedDate(Date modifiedDate) {
		this.modifiedDate = modifiedDate;
	}

	@Override
	public int hashCode() {
		return this.categoryId.intValue();
	}

	@Override
	public boolean equals(Object obj) {
		boolean sameSame = false;

		if (obj != null && obj instanceof Category) {
			sameSame = this.categoryId.equals(((Category) obj).categoryId);
		}

		return sameSame;
	}
}
